home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Language/OS - Multiplatform Resource Library
/
LANGUAGE OS.iso
/
lisp
/
kcl
/
akcl
/
akcl1615.lha
/
c
/
rel_rios.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-08-14
|
8KB
|
267 lines
/* Copyright William Schelter. All rights reserved. This file does
the low level relocation which tends to be very system dependent.
It is included by the file sfasl.c
*/
typedef int (*FUNC)();
extern int akcltoc;
extern int toc_start;
static int current_toc;
static int ptrgl_offset = 0;
static int ptrgl_text;
static int akcltoc_used=0;
/* This is an alternating list of addresses x1,y1,x2,y2,... where
relocation entries for changing value in address x1 shold be read as changing
it in y1 */
static int toc_addresses_to_relocate [10];
static int *next_toc_addresses_to_relocate = toc_addresses_to_relocate ;
static int akcltoc_thisload;
static int begun_relocate = 0;
static int set_rel_bits(address,bits,val)
char *address;
int val;
int bits;
{ bits += 1;
if ( bits <= 16)
{unsigned short y = *(unsigned short *)address ;
y = y & (~0 << bits) ;
y |= (val & ~(~0 << bits));
*(unsigned short *)address = val;
}
else
{unsigned int y = *(unsigned int *)address ;
y = y & (~0 << bits) ;
y |= (val & ~(~0 << bits));
*(unsigned int *)address = y;
}
}
/*
800b0000 l r0,0x0(r11)
90410014 st r2,0x14(r1)
7c0903a6 mtctr r0
804b0004 l r2,0x4(r11)
816b0008 l r11,0x8(r11)
4e800420 bctr
*/
int myptrgl[6] = {
0x800b0000, 0x90410014, 0x7c0903a6, 0x804b0004,
0x816b0008, 0x4e800420};
/* 7d8903a6 mtctr r12
4e800420 bctr
*/
static int jmp_r12[2] = { 0x7d8903a6, 0x4e800420};
#define SYM_SMC(sym) (((union auxent *)(sym+1))->x_csect.x_smclas)
#define SYM_TOC_ADDR(sym) (((union auxent *)(sym+1))->x_csect.x_parmhash)
/* #define SYM_USED(sym) (((union auxent *)(&sym[1]))->x_csect.x_snhash) */
#define TC_SYMBOL_P(sym) ((sym)->n_scnum == DATA_NSCN && NUM_AUX((sym)) && \
(SYM_SMC(sym) == XMC_TC0 || SYM_SMC(sym) == XMC_TC))
int FIXtemp ;
static int intcmp2(x,y)
int *x,*y;
{ return (*x - *y);
}
#define TOP6 (~0 << 26)
#define BR_IN_DATA_P(x) (((x) & TOP6) == (DBEGIN & TOP6))
relocate()
{ struct syment *sym = &symbol_table[relocation_info.r_symndx];
char *where;
describe_sym(relocation_info.r_symndx);
where = the_start + relocation_info.r_vaddr;
dprintf (where has %x , *(int *)where);
dprintf( at %x -->, where );
if(begun_relocate == 0)
{int n = next_toc_addresses_to_relocate - toc_addresses_to_relocate;
begun_relocate = 1;
FIXtemp = 0; /* dummy reference for export problem */
qsort((char *)toc_addresses_to_relocate, n/2 , 2*sizeof(int), intcmp2);
next_toc_addresses_to_relocate
= toc_addresses_to_relocate;}
switch(RELOC_RTYPE(relocation_info))
{ int *q;
case R_TOC: /* TOC_ILodx */
set_rel_bits(where,RELOC_RLEN(relocation_info), sym->n_value - toc_start) ;
break;
case R_POS: /* Pos_Rel */
if (where == *next_toc_addresses_to_relocate)
{where = next_toc_addresses_to_relocate [1];
next_toc_addresses_to_relocate += 2;}
if ( sym->n_scnum == N_UNDEF || TC_SYMBOL_P(sym))
set_rel_bits(where,RELOC_RLEN(relocation_info), sym->n_value);
else
set_rel_bits(where,RELOC_RLEN(relocation_info), (*(int *)where)+ sym->n_value);
break;
case R_BR: /* Brn_Sel */
{int link_bit = ((((int *)where)[0]) & 1);
if (((((int *)where)[0]) & TOP6 ) == 0x48000000) /* bl or b relative */
{
if (((int *)where)[1] == 0x80410014) /* l r2,0x14(r1) */
{int x = SYM_TOC_ADDR(sym);
if (x)
{ ((int *)where)[0] = 0x81820000 ; /* l r12,0x0(r2) */
set_rel_bits(where+2,15,x - toc_start);
(((int *)where)[1] = 0x48000000); /* b relative */
set_rel_bits(where+4, 0x19, ((int) jmp_r12) - ((int) where + 4 ));
((int *)where)[1] |= link_bit; /* link bit */
break;
}
else /* must be ptrgl */
if (BR_IN_DATA_P(sym->n_value))
{set_rel_bits(where, 0x19, sym->n_value - (int) where);
((int *)where)[0] |= link_bit; /* link bit */
break;}
}
else
if (BR_IN_DATA_P(sym->n_value))
{set_rel_bits(where, 0x19, sym->n_value - (int) where);
((int *)where)[0] |= link_bit; /* link bit */
break;}}
else
FEerror("The type of Br_sel was new ",0,0);
}
default:
fprintf(stdout, "%d: unsupported relocation type.",
RELOC_RTYPE(relocation_info) );
FEerror("The relocation type was unknown",0,0);
}
dprintf( %x,*(int *)where);
}
fix_undef_toc_address(answ,sym,str)
char *str;
struct syment *sym;
struct node *answ;
/* undefined sym */
{ if (BR_IN_DATA_P(answ->address)) return;
if (answ->tc_offset == 0)
{ answ->tc_offset = ( akcltoc + akcltoc_used - toc_start);
* ((int *)( akcltoc + akcltoc_used)) = answ->address;
akcltoc_used += sizeof(char *);
}
if (NUM_AUX(sym))
SYM_TOC_ADDR(sym) = (toc_start + answ->tc_offset);
else printf("symbol should have aux entry");
return;
}
#ifdef DEBUG
#undef describe_sym
#define describe_sym(x) do{if(sfasldebug) describe_sym1(x);} while (0)
describe_sym1(n)
int n;
{char *str;
char tem[9];
struct syment *sym;
sym= &symbol_table[n];
str= sym->n_zeroes == 0 ?
&my_string_table[sym->n_offset] :
(sym->n_name[SYMNMLEN -1] ?
/* MAKE IT NULL TERMINATED */
(strncpy(tem,sym->n_name,
SYMNMLEN),tem):
sym->n_name );
printf ("sym-index = %d table entry at %x",n,&symbol_table[n]);
printf("symbol is (%s):\nsymbol_table[n]._n._n_name %s\nsymbol_table[n]._n._n_n._n_zeroes %d\nsymbol_table[n]._n._n_n._n_offset %d\nsymbol_table[n]._n._n_nptr[0] %d\nsymbol_table[n]._n._n_nptr[n] %d\nsymbol_table[n].n_value %d\nsymbol_table[n].n_scnum %d nsymbol_table[n].n_type %d\nsymbol_table[n].n_sclass %d\nsymbol_table[n].n_numaux %d", str,
symbol_table[n]._n._n_name,
symbol_table[n]._n._n_n._n_zeroes ,
symbol_table[n]._n._n_n._n_offset ,
symbol_table[n]._n._n_nptr[0] ,
symbol_table[n]._n._n_nptr[1] ,
symbol_table[n].n_value ,
symbol_table[n].n_scnum ,
symbol_table[n].n_type ,
symbol_table[n].n_sclass ,
symbol_table[n].n_numaux );
}
#endif
/* allocate toc space in the preallocated region starting at akcltoc.
If a symbol already has a toc entry, use that instead
*/
setup_for_aix_load()
{ bzero(toc_addresses_to_relocate,sizeof(toc_addresses_to_relocate));
next_toc_addresses_to_relocate= toc_addresses_to_relocate;
akcltoc_thisload = akcltoc + akcltoc_used;
begun_relocate=0;
}
char *
sym_name(sym)
struct syment *sym;
{static char tem[SYMNMLEN +1];
char *name;
tem[SYMNMLEN] = '0';
name = SYM_NAME(sym);
return name;}
allocate_toc(sym)
struct syment *sym;
/* sym is a symbol in the data section with an aux entry */
{ if (SYM_SMC(sym) == XMC_TC0)
{ sym->n_value = toc_start; return 1;}
if (SYM_SMC(sym) == XMC_TC)
{struct node *answ = find_sym(sym,0);
if (answ && answ->tc_offset)
{ sym->n_value = toc_start + answ->tc_offset;
return 1;}
{char *na = sym_name(sym);
#ifdef SYM_USED
if (TC_SYMBOL_P(sym) && SYM_USED(sym) == 0)
return 0;
#endif
if (answ == 0 && *na && *na != '_')
printf("(strange TC synbol %s[%d])",na,sym - symbol_table);}
{int old_value;
(*next_toc_addresses_to_relocate++) = sym->n_value + start_address;
sym->n_value = akcltoc + akcltoc_used;
if (answ) answ->tc_offset = sym->n_value - toc_start;
(*next_toc_addresses_to_relocate++) = sym->n_value;
*((int *)(next_toc_addresses_to_relocate[-1])) =
*((int *)(next_toc_addresses_to_relocate[-2]));
akcltoc_used += sizeof(long int);
if (next_toc_addresses_to_relocate - toc_addresses_to_relocate
>= (sizeof(toc_addresses_to_relocate)/sizeof(int)))
FEerror("ran out");
if (akcltoc_used > 24000) FEerror("toc exhausted");
return 1;
}}
return 0;
}